home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet internetowy / Przegladarki internetowe / Mozilla Seamonkey 1.0.5 pl / seamonkey-1.0.5.pl-PL.win32.installer.exe / BROWSER.XPI / bin / chrome / toolkit.jar / content / global / nsTreeController.js < prev    next >
Encoding:
Text File  |  2004-04-17  |  9.2 KB  |  324 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1998
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Blake Ross <blaker@netscape.com> (Original Author)
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  27.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. // helper routines, for doing rdf-based cut/copy/paste/etc
  40. // this needs to be more generic!
  41.  
  42. const nsTransferable_contractid = "@mozilla.org/widget/transferable;1";
  43. const clipboard_contractid = "@mozilla.org/widget/clipboard;1";
  44. const rdf_contractid = "@mozilla.org/rdf/rdf-service;1";
  45. const supportswstring_contractid = "@mozilla.org/supports-string;1";
  46. const rdfc_contractid = "@mozilla.org/rdf/container;1";
  47.  
  48. const nsISupportsString = Components.interfaces.nsISupportsString;
  49. const nsIClipboard = Components.interfaces.nsIClipboard;
  50. const nsITransferable = Components.interfaces.nsITransferable;
  51. const nsIRDFLiteral = Components.interfaces.nsIRDFLiteral;
  52. const nsIRDFContainer = Components.interfaces.nsIRDFContainer;
  53.  
  54. var gRDF;
  55. var gClipboard;
  56.  
  57. function isContainer(tree, index)
  58. {
  59.   return tree.treeBoxObject.view.isContainer(index);
  60. }
  61.  
  62. function isContainerOpen(tree, index)
  63. {
  64.   return tree.treeBoxObject.view.isContainerOpen(index);
  65. }
  66.  
  67. function nsTreeController_SetTransferData(transferable, flavor, text)
  68. {
  69.   if (!text)
  70.     return;
  71.   var textData = Components.classes[supportswstring_contractid].createInstance(nsISupportsString);
  72.   textData.data = text;
  73.  
  74.   transferable.addDataFlavor(flavor);
  75.   transferable.setTransferData(flavor, textData, text.length*2);
  76. }
  77.  
  78. function nsTreeController_copy()
  79. {
  80.   var rangeCount = this.treeSelection.getRangeCount();
  81.   if (rangeCount < 1)
  82.     return false;
  83.    
  84.   // Build a url that encodes all the select nodes 
  85.   // as well as their parent nodes
  86.   var url = "";
  87.   var text = "";
  88.   var html = "";
  89.   var min = new Object();
  90.   var max = new Object();
  91.  
  92.   for (var i = rangeCount - 1; i >= 0; --i) {
  93.     this.treeSelection.getRangeAt(i, min, max);
  94.     for (var k = max.value; k >= min.value; --k) {
  95.       // If one of the selected items is
  96.       // a container, ignore it.
  97.       if (isContainer(this.tree, k))
  98.         continue;
  99.       var col = this.tree.columns["URL"];
  100.       var pageUrl  = this.treeView.getCellText(k, col);
  101.       col = this.tree.columns["Name"];
  102.       var pageName = this.treeView.getCellText(k, col);
  103.  
  104.       url += "ID:{" + pageUrl + "};";
  105.       url += "NAME:{" + pageName + "};";
  106.  
  107.       text += pageUrl + "\r";
  108.       html += "<a href='" + pageUrl + "'>";
  109.       if (pageName) html += pageName;
  110.         html += "</a><p>";
  111.     } 
  112.   }
  113.  
  114.   if (!url)
  115.     return false;
  116.  
  117.   // get some useful components
  118.   var trans = Components.classes[nsTransferable_contractid].createInstance(nsITransferable);
  119.   
  120.   if (!gClipboard)
  121.     gClipboard = Components.classes[clipboard_contractid].getService(Components.interfaces.nsIClipboard);
  122.  
  123.   gClipboard.emptyClipboard(nsIClipboard.kGlobalClipboard);
  124.  
  125.   this.SetTransferData(trans, "text/unicode", text);
  126.   this.SetTransferData(trans, "moz/bookmarkclipboarditem", url);
  127.   this.SetTransferData(trans, "text/html", html);
  128.  
  129.   gClipboard.setData(trans, null, nsIClipboard.kGlobalClipboard);
  130.   return true;
  131. }
  132.  
  133. function nsTreeController_cut()
  134. {
  135.   if (this.copy()) {
  136.     this.doDelete();
  137.     return true;            // copy succeeded, don't care if delete failed
  138.   }
  139.   return false;             // copy failed, so did cut
  140. }
  141.  
  142. function nsTreeController_selectAll()
  143. {
  144.   this.treeSelection.selectAll();
  145. }
  146.  
  147. function nsTreeController_delete()
  148. {  
  149.   var rangeCount = this.treeSelection.getRangeCount();
  150.   if (rangeCount < 1)
  151.     return false;      
  152.   
  153.   var datasource = this.tree.database;
  154.   var dsEnum = datasource.GetDataSources();
  155.   dsEnum.getNext();
  156.   var ds = dsEnum.getNext()
  157.                  .QueryInterface(Components.interfaces.nsIRDFDataSource);
  158.  
  159.   var count = this.treeSelection.count;
  160.   
  161.   // XXX 9 is a random number, just looking for a sweetspot
  162.   // don't want to rebuild tree content for just a few items
  163.   if (count > 9) {
  164.     ds.beginUpdateBatch();
  165.   }
  166.  
  167.   var min = new Object(); 
  168.   var max = new Object();
  169.   var dirty = false;
  170.   for (var i = rangeCount - 1; i >= 0; --i) {
  171.     this.treeSelection.getRangeAt(i, min, max);
  172.     for (var k = max.value; k >= min.value; --k) {
  173.       if (!gRDF)
  174.         gRDF = Components.classes[rdf_contractid].getService(Components.interfaces.nsIRDFService);
  175.  
  176.       var IDRes = this.treeBuilder.getResourceAtIndex(k);
  177.       if (!IDRes)
  178.         continue;
  179.  
  180.       var root = this.tree.getAttribute('ref');
  181.       var parentIDRes;
  182.       try {
  183.         parentIDRes = this.treeBuilder.getResourceAtIndex(this.treeView.getParentIndex(k));
  184.       }
  185.       catch(ex) {
  186.         parentIDRes = gRDF.GetResource(root);
  187.       }
  188.       if (!parentIDRes)
  189.         continue;
  190.       
  191.       // otherwise remove the parent/child assertion then
  192.       var containment = gRDF.GetResource("http://home.netscape.com/NC-rdf#child");
  193.       ds.Unassert(parentIDRes, containment, IDRes);
  194.       dirty = true;
  195.     }
  196.   }
  197.  
  198.   if (count > 9) {
  199.     ds.endUpdateBatch();
  200.   }
  201.  
  202.   if (dirty) {    
  203.     try {
  204.       var remote = datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
  205.       remote.Flush();
  206.     } catch (ex) {
  207.     }
  208.   }
  209.   if (max.value) {
  210.     var newIndex = max.value - (max.value - min.value);
  211.     if (newIndex >= this.treeView.rowCount)
  212.       --newIndex;
  213.     this.treeSelection.select(newIndex);
  214.   }
  215.   return true;
  216. }
  217.  
  218. function nsTreeController(tree)
  219. {
  220.   this._tree = tree;
  221.   tree.controllers.appendController(this);
  222. }
  223.  
  224. nsTreeController.prototype = 
  225. {
  226.   _treeSelection: null,
  227.   _treeView: null,
  228.   _treeBuilder: null,
  229.   _treeBoxObject: null,
  230.   _tree: null,
  231.   get tree()
  232.   {
  233.     return this._tree;
  234.   },
  235.   get treeBoxObject()
  236.   {
  237.     if (this._treeBoxObject)
  238.       return this._treeBoxObject;
  239.     return this._treeBoxObject = this.tree.treeBoxObject;
  240.   },
  241.   get treeView()
  242.   {
  243.     if (this._treeView)
  244.       return this._treeView;
  245.     return this._treeView = this.tree.treeBoxObject.view;
  246.   },
  247.   get treeSelection()
  248.   {
  249.     if (this._treeSelection)
  250.       return this._treeSelection;
  251.     return this._treeSelection = this.tree.view.selection;
  252.   },
  253.   get treeBuilder()
  254.   {
  255.     if (this._treeBuilder)
  256.       return this._treeBuilder;
  257.     return this._treeBuilder = this.tree.builder.
  258.                                    QueryInterface(Components.interfaces.nsIXULTreeBuilder);
  259.   },
  260.   SetTransferData : nsTreeController_SetTransferData,
  261.  
  262.   supportsCommand: function(command)
  263.   {
  264.     switch(command)
  265.     {
  266.       case "cmd_cut":
  267.       case "cmd_copy":
  268.       case "cmd_delete":
  269.       case "cmd_selectAll":
  270.         return true;
  271.       default:
  272.         return false;
  273.     }
  274.   },
  275.  
  276.   isCommandEnabled: function(command)
  277.   {
  278.     var haveCommand;
  279.     switch (command)
  280.     {
  281.       // commands which do not require selection              
  282.       case "cmd_selectAll":
  283.         var treeView = this.treeView;
  284.         return (treeView.rowCount !=  treeView.selection.count);
  285.                 
  286.       // these commands require selection
  287.       case "cmd_cut":
  288.         haveCommand = (this.cut != undefined);
  289.         break;
  290.       case "cmd_copy":
  291.         haveCommand = (this.copy != undefined);
  292.         break;
  293.       case "cmd_delete":
  294.         haveCommand = (this.doDelete != undefined);
  295.         break;
  296.     }
  297.         
  298.     // if we get here, then we have a command that requires selection
  299.     var haveSelection = (this.treeSelection.count);
  300.     return (haveCommand && haveSelection);
  301.   },
  302.  
  303.   doCommand: function(command)
  304.   {
  305.     switch(command)
  306.     {
  307.       case "cmd_cut":
  308.         return this.cut();
  309.       case "cmd_copy":
  310.         return this.copy();
  311.       case "cmd_delete":
  312.         return this.doDelete();        
  313.       case "cmd_selectAll":
  314.         return this.selectAll();
  315.     }
  316.     return false;
  317.   },
  318.   copy: nsTreeController_copy,
  319.   cut: nsTreeController_cut,
  320.   doDelete: nsTreeController_delete,
  321.   selectAll: nsTreeController_selectAll
  322. }
  323.  
  324.